#include "CompressDirector.h"
#include <iostream>
using namespace std;

CompressDirector::CompressDirector(const char* iFile, const char* oFile)
{
	_iFile.assign(iFile);
	_oFile.assign(oFile);
};

CompressDirector::~CompressDirector()
{
};

bool CompressDirector::Compress(FileReader* r, Coder* c, CompressFileWriter* w)
{
	cout << "> Will code " << _iFile << ", "
		 << " Output to " << _oFile << "." << endl;
	cout << "> Initing.." << endl;
	if(r->OpenFile(_iFile.c_str()) == false)
		return false;
	if(w->OpenOutputFile(_oFile.c_str()) == false)
		return false;
	while(!r->Eof())
	{
		BYTE tmp = r->ReadByte();
		if(r->Good())
			c->Input(tmp);
	}
	cout << "> Parsing.." << endl;
	c->Parse();

	cout << "> Writing original filename.." << endl;
	w->WriteString(_iFile.c_str());

	cout << "> Writing dictionary.." << endl;
	w->WriteInt(c->GetDictItemCount());
	DictItem di;
	while(c->GetNextDictItem(&di))
	{
		w->WriteDict(di._code._bitSize, di._code._code, di._data._dataSize, di._data._data);
	}
	w->WriteInt(c->GetDataCount());

	cout << "> Writing codes.." << endl;
	r->ResetFile();
	BYTE data[256];
	DataCode oc;
	while(!r->Eof())
	{
		int i;
		for(i = 0; i < 256; ++i)
		{
			if(r->Eof())
			{
				--i;
				break;
			}
			data[i] = r->ReadByte();
		}
		c->InputBlock(data, i);
		while(c->GetNextCode(&oc))
		{
			w->WriteData(oc._code, oc._bitSize);
		}
	}

	r->CloseFile();
	w->CloseFile();

	cout << "> Complete." << endl;
	cout << "> Original file bytes: " << r->GetInFileBytes() << "." << endl;
	cout << "> Compressed file bytes: " << w->GetWriteBytes() << "." << endl;
	cout << "> Compressed Rate is " << (w->GetWriteBytes()/(float)(r->GetInFileBytes()))*100 << "% ." << endl;
	return true;
};